package dfs;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import virtualdisk.Disk;

import common.Constants;
import common.DFileID;
import dblockcache.Cache;
import dblockcache.DBufferCache;

public class FileSystem extends DFS {
	
	private Disk _disk;
	private Cache _cache;
	
	private Inode[] _inodes;
	private boolean[] _blocks;
	
	@Override
	public void init() throws FileNotFoundException, IOException {
		_disk = new Disk(getVolume(), getFormat());
		_cache = new Cache(Constants.NUM_OF_CACHE_BLOCKS);
		_inodes = new Inode[Constants.MAX_DFILES];
		_blocks = new boolean[Constants.NUM_OF_BLOCKS];
		
		
		for (int i=0; i<Constants.MAX_DFILES ; i++){
			//check to see if there are Inodes there.
			//if so, keep them, if not, make new ones.
		}
	}

	@Override
	public DFileID createDFile() {
		DFileID id = null;
		
		//DFileID id = new DFileID();
		for (Inode node: _inodes){
			if (node.isFree){
				id = node.getID();
				node.toggleFree();
			}
		}
		return id;
	}

	@Override
	public void destroyDFile(DFileID dFID) {
		// Get Inode for the appropriate ID
		// loop through Inode to free all the blocks in that file
		// for 
		// after that (to avoid races) free the Inode
		

	}

	@Override
	public int read(DFileID dFID, byte[] buffer, int startOffset, int count) {
		// pseudo code
		
		// start counter at -1 to return if read fails
		int counter = -1;
		
		// use DFileID to get index in _inodes array
		Inode node = _inodes[dFID.getID()];
		// loop over the blocks listed in the Inode's blockArray,
		
		// for each, check to see if the block is in the cache
		// if in cache, read from it
		// when reading, increase counter
		// when not in cache, fetch it from disk
		return counter;
	}

	@Override
	public int write(DFileID dFID, byte[] buffer, int startOffset, int count) {
		// make new Inode to replace current Inode in array,
		Inode newNode = new Inode(dFID);
		//release old blocks pointed to by Inode, by updating _blocks
		Inode oldNode = _inodes[dFID.getID()];

		for (int blockNumber :oldNode.getBlocks()) {
			_blocks[blockNumber] = false;
		}
		
		int counter = -1
		
		// start writing to new blocks. 
		// blocks_needed = count / block_size
		// obtain blocks from free list
		// split up buffer into block chunks, and call writes to the cache
		

		
		return counter;
	}

	@Override
	public int sizeDFile(DFileID dFID) {
		int size = _inodes[dFID.getID()].getSize();
		return size;
	}

	@Override
	public List<DFileID> listAllDFiles() {
		List<DFileID> IDlist = new ArrayList<DFileID>();
		
		for (Inode node: _inodes){
			if (!node.isFree()){
				IDlist.add(node.getID());
			}
		}
		return IDlist;
	}

	@Override
	public void sync() {
		_cache.sync();
	}

}
